package main

import (
	a "Ljohn/bufioTest/ioTest"
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"
)

func main() {
	//test1()
	//test()
	//test2()
	//generation()
	testMain()
}

func testMain() {
	flag.Parse()
	file1 := "./random1.txt"
	file2 := "./random2.txt"
	file3 := "./random3.txt"
	file4 := "./random4.txt"
	blocksize, _ := strconv.Atoi(flag.Arg(0))
	var start, end time.Time
	start = time.Now()
	a.Read1(file1, blocksize)
	end = time.Now()
	fmt.Printf("file/Read() cost time %v\n", end.Sub(start))
	start = time.Now()
	a.Read2(file2, blocksize)
	end = time.Now()
	fmt.Printf("bufio/Read() cost time %v\n", end.Sub(start))
	start = time.Now()
	a.Read3(file4)
	end = time.Now()
	fmt.Printf("ioutil.ReadAll() cost time %v\n", end.Sub(start))
	start = time.Now()
	a.Read4(file3)
	end = time.Now()
	fmt.Printf("ioutil.ReadFile() cost time %v\n", end.Sub(start))
}

func generation() {
	flag.Parse()
	filesizeMB, err := strconv.Atoi(flag.Arg(0)) //1-500MB大小的文件
	if err != nil {
		panic(err)
	}
	if filesizeMB > 500 {
		panic("too large file,>500MB")
	}
	RandFile("./random1.txt", filesizeMB)
	RandFile("./random2.txt", filesizeMB)
	RandFile("./random3.txt", filesizeMB)
	RandFile("./random4.txt", filesizeMB)
	fmt.Printf("Created 4 files, each file size is %d MB.", filesizeMB)
}

func test1() {
	var text = "abcdqwe"
	scanner := bufio.NewScanner(strings.NewReader(text))
	var res []byte
	scanner.Buffer(res, 1024)
	for scanner.Scan() {
		x := scanner.Bytes()
		fmt.Println(x)
	}
}

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

// https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-golang
func RandStringBytes(n int) []byte {
	b := make([]byte, n)
	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}
	return b
}

func RandFile(path string, filesizeMB int) {
	b := RandStringBytes(filesizeMB * 1024) //生成1-500KB大小的随机字符串
	bb := make([]byte, filesizeMB*1024*1024)
	for i := 0; i < 1024; i++ { //复制1024遍
		copy(bb[len(b)*i:len(b)*(i+1)], b)
	}
	//fmt.Printf("%s",b)
	ioutil.WriteFile(path, bb, 0666)
}

func test() {
	const input = "1234 5678 12345 679012345678901"
	scanner := bufio.NewScanner(strings.NewReader(input))
	// 通过包装现有的ScanWords函数来创建自定义拆分功能。
	split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
		advance, token, err = bufio.ScanWords(data, atEOF)
		if err == nil && token != nil {
			_, err = strconv.ParseInt(string(token), 10, 32)
		}
		return
	}
	// 设置扫描操作的分割功能。
	scanner.Split(split)
	// 验证输入
	for scanner.Scan() {
		fmt.Printf("%s\n", scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		fmt.Printf("Invalid input: %s\n", err)
	}
}

func test2() {
	const input1 = "1,2,3,4,"
	scanner := bufio.NewScanner(strings.NewReader(input1))
	// 定义一个以逗号分隔的分割函数。
	onComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
		for i := 0; i < len(data); i++ {
			if data[i] == ',' {
				return i + 1, data[:i], nil
			}
		}
		// 有一个最终的令牌要交付，可能是空字符串。
		// 在这里返回bufio.ErrFinalToken告诉Scan，在此之后没有更多的标记
		// 但不会触发从扫描本身返回的错误。
		return 0, data, bufio.ErrFinalToken
	}
	scanner.Split(onComma)
	// Scan.
	for scanner.Scan() {
		fmt.Printf("%q \n", scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading input:", err)
	}
}
